package com.hm.core;

import java.lang.reflect.Method;

import javax.servlet.http.HttpServletRequest;

import com.hm.base.service.AuthorizationService;
import com.hm.base.vo.LoginSubscriberVo;
import com.hm.common.annotation.WebClientRequestIntercept;
import com.hm.common.exception.ErrorCode;
import com.hm.common.exception.ServiceException;
import com.hm.common.util.CommonUtil;
import com.hm.common.util.EncryptUtil.AES;

import lombok.extern.slf4j.Slf4j;

/**
 * @author shishun.wang
 * @date 2017年12月8日 下午3:03:25
 * @version 1.0
 * @describe
 */
@Slf4j
public class ApiAspectSuport {

	private LoginSubscriberVo checkRemoteRequestToken(HttpServletRequest request, AuthorizationService authorizationService) {
		String token = request.getHeader(SdkConfig.REMOTE_CLIENT_AUTHORIZATION);

		Object obj = request.getSession().getAttribute(SdkConfig.REMOTE_CLIENT_AUTHORIZATION);
		if (CommonUtil.isEmpty(token) && null != obj) {// 兼容session登陆用户
			token = obj.toString();
		}
		if (CommonUtil.isEmpty(token)) {
			log.error("token丢失,会话超时重新登陆");
			throw ServiceException.warning(ErrorCode.SESSION_TIME_OUT);
		}

		Long subscriberId = 0l;
		Long loginTime = 0l;
		try {// 验证token 是否合法
			String[] decrypt = AES.decrypt(token).split(":");
			subscriberId = Long.valueOf(decrypt[0]);
			loginTime = Long.valueOf(decrypt[1]);
		} catch (Exception e) {
			log.error("token解析失败", e);
			throw ServiceException.warning(ErrorCode.NO_DATA_ACCESS);
		}

		LoginSubscriberVo subscriberVo = authorizationService.loadLoginToken(subscriberId);
		if (CommonUtil.isEmpty(subscriberVo) || (loginTime != subscriberVo.getCurrentLoginTime())) {
			log.error("token丢失,会话超时重新登陆");
			throw ServiceException.warning(ErrorCode.SESSION_TIME_OUT);
		}

		return subscriberVo;
	}

	/**
	 * @param method
	 * @param request
	 * @param authorizationService
	 * @param isDevModel
	 *            开发者模式
	 * @param dataAuth
	 *            数据权限校验
	 */
	public void process(Method method, HttpServletRequest request, AuthorizationService authorizationService, boolean isDevModel, boolean dataAuth) {
		if (isDevModel) {
			request.setAttribute(SdkConfig.REMOTE_CLIENT_AUTHORIZATION_DEV, AES.encrypt("1:" + System.currentTimeMillis()));
			return;
		}

		WebClientRequestIntercept intercept = method.getAnnotation(WebClientRequestIntercept.class);
		if (null == intercept) {
			this.dataAuthCheck(request, authorizationService, method, dataAuth);
			return;
		}

		if (!intercept.auth()) {
			return;
		}

		this.dataAuthCheck(request, authorizationService, method, dataAuth);
	}

	private void dataAuthCheck(HttpServletRequest request, AuthorizationService authorizationService, Method method,  boolean dataAuth) {
		LoginSubscriberVo subscriberVo = checkRemoteRequestToken(request, authorizationService);

		if (!dataAuth) {
			log.info("没开启数据权限");
			return;
		}

		Class<?> objClass = method.getDeclaringClass();
		String authorizationCode = objClass.getPackage().getName() + "." + objClass.getSimpleName() + "::" + method.getName();
		// 校验用户真实数据权限
		if (!authorizationService.remoteClienAuthCodeCheck(authorizationCode, subscriberVo.getRoles())) {
			log.error("{}用户无权使用该接口[{}],无权使用该授权code[{}]", subscriberVo.getAccount(), request.getRequestURL(), authorizationCode);
			throw ServiceException.warning(ErrorCode.NO_DATA_ACCESS);
		}
	}
}
